﻿
#region Using Directives.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using ActiproSoftware.Drawing;
using ActiproSoftware.SyntaxEditor;
using ActiproSoftware.SyntaxEditor.Commands;
using BrightIdeasSoftware;
using GDFlacTool.Client;
using GDFlacTool.Common;
using GDFlacTool.Properties;

#endregion

namespace GDFlacTool.Forms
{
    public partial class FormTitleEditor : Form
    {
        #region Fields.

        private readonly string _currentDirectoryPath = string.Empty;
        private string _currentFilePath = string.Empty;
        private readonly TrackTitleCollection _tracks;
        private readonly TypedObjectListView<TrackTitle> _trackList;
        private FormFindReplace _findReplaceForm;
        private readonly FindReplaceOptions _findReplaceOptions = new FindReplaceOptions();
        private bool _isSorted = true;
        protected MruStripMenu MruMenu;
        private const int PrintDocumentMaxLengthName = 75;
        private readonly string _fileList = string.Empty;
        private readonly string _lastOpenedFile = string.Empty;
        private int _selectedFormatIndex = 0;


        #endregion

        #region Constructors.

        public FormTitleEditor(string currentPath, TrackTitleCollection tracks)
        {
            InitializeComponent();

            MruMenu = new MruStripMenu(mnuRecentFiles, OnMruFile, 16);

            syntaxEditor.Document.UndoRedoStateChanged += (UndoRedoStateChanged);

            VisualStudio2005SyntaxEditorRenderer renderer = new VisualStudio2005SyntaxEditorRenderer();

            BackgroundFill fill = new SolidColorBackgroundFill(Color.WhiteSmoke);

            renderer.LineNumberMarginBackgroundFill = fill;

            syntaxEditor.Renderer = renderer;

            _trackList = new TypedObjectListView<TrackTitle>(objectListView);

            _currentDirectoryPath = currentPath;

            _tracks = tracks;

            slbTotalFiles.Text = string.Format("Total Files: {0:# ##0}", _tracks.Count);

            _fileList = TrackTitleEditorSettings.Default.RecentFiles;

            _lastOpenedFile = TrackTitleEditorSettings.Default.LastFile;

            //splitContainer.SplitterDistance = TrackTitleEditorSettings.Default.SplitterDistance;

            Location = TrackTitleEditorSettings.Default.Position;

            ClientSize = TrackTitleEditorSettings.Default.ClientSize;

            if (TrackTitleEditorSettings.Default.FormatString != null)
            {
                foreach (string format in TrackTitleEditorSettings.Default.FormatString)
                {
                    cboFormatString.Items.Add(format);
                }
            }
            else
            {
                cboFormatString.Items.Add(string.Empty);
            }

            int index = cboFormatString.Items.IndexOf(TrackTitleEditorSettings.Default.LastFormatString);

            if(index >= 0)
            {
                cboFormatString.SelectedIndex = index;
            }

            if(string.IsNullOrEmpty(cboFormatString.Text))
            {
                btnPreview.Enabled = false;
                btnUpdate.Enabled = false;
            }
        }

        #endregion

        #region Properties.

        public TrackTitleCollection GetTitles
        {
            get { return _tracks; }
        }

        #endregion

        #region Form Events.

        private void FormTitleEditor_Load(object sender, EventArgs e)
        {
            olvColumnFileName.ImageGetter = delegate(object rowObject)
            {
                TrackTitle track = (TrackTitle)rowObject;

                if (string.IsNullOrEmpty(track.FileName) || string.IsNullOrEmpty(track.Title))
                {
                    return 1;
                }
                
                return 0;
            };

            _trackList.Objects = _tracks;

            objectListView.Sort(0);

            HasClipboardText();

            if (!string.IsNullOrEmpty(_fileList))
            {
                MruMenu.LoadFromString(_fileList);
                mnuRecentFiles.Enabled = true;
            }

            if(!string.IsNullOrEmpty(_lastOpenedFile) && File.Exists(_lastOpenedFile))
            {
                string textFilePath = Path.GetDirectoryName(_lastOpenedFile);
                string currentDir = _currentDirectoryPath;

                if(textFilePath == currentDir)
                    Open(_lastOpenedFile);
            }

            tsbTextEditor.ImageList = imlMenu;
        }

        private void FormTitleEditor_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (syntaxEditor.Document.Modified)
            {
                const string msg = "There are changes to the open text file, would you like to save the changes before closing?";

                DialogResult result = MessageBox.Show(msg,"Save Changes?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
                   
                if (result == DialogResult.Yes)
                {
                    Save();
                }
                else if (result == DialogResult.Cancel)
                {
                    // Stop the closing and return to the form 
                    e.Cancel = true;
                }
                else
                {
                    e.Cancel = false;
                }
            }

            TrackTitleEditorSettings.Default.RecentFiles = MruMenu.SaveToString();

            if (!string.IsNullOrEmpty(syntaxEditor.Document.Filename))
                TrackTitleEditorSettings.Default.LastFile = syntaxEditor.Document.Filename;

            TrackTitleEditorSettings.Default.Position = Location;

            TrackTitleEditorSettings.Default.ClientSize = ClientSize;

            TrackTitleEditorSettings.Default.SplitterDistance = splitContainer.SplitterDistance;

            TrackTitleEditorSettings.Default.LastFormatString = cboFormatString.Text;

            TrackTitleEditorSettings.Default.Save();
        }

        private void OnMruFile(int number, String filename)
        {
            if (File.Exists(filename))
            {
                Open(filename);
            }
            else
            {
                string message = string.Format("The file: {0} can not be opened and will be removed from the Recent list(s)", filename);

                MessageBox.Show(this, message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                MruMenu.RemoveFile(number);

                if (MruMenu.MenuItems.Count == 0)
                {
                    mnuRecentFiles.Enabled = false;
                }
            }
        }

        #endregion

        #region Button Events.

        private void btnPreview_Click(object sender, EventArgs e)
        {
            _trackList.ListView.BeginUpdate();

            int index = 0;

            IList<TrackTitle> tracks = _trackList.Objects;

            DocumentLineCollection trackLines = syntaxEditor.Document.Lines;

            if(trackLines.Count > tracks.Count)
            {
                List<string> missingTitles = GetMissingTitles(trackLines, tracks);

                FormShowMissingTitles frm = new FormShowMissingTitles(missingTitles);

                frm.ShowDialog(this);
            }

            foreach (TrackTitle track in tracks)
            {
                if(index < tracks.Count)
                {
                    if(index < trackLines.Count)
                    {
                        CreateTagsFromFormatString(cboFormatString.Text, trackLines[index].Text, track);

                        SaveFormatString(cboFormatString.Text);
                    }
                    else
                    {
                        track.Title = string.Empty;
                        track.Tracknumber = string.Empty;
                    }
                }

                index++;
            }

           _trackList.Objects = tracks;

           _trackList.ListView.EndUpdate();
        }

        private void SaveFormatString(string format)
        {
            if(string.IsNullOrEmpty(format))
                return;

            if(cboFormatString.Items.Contains(format))
            {
                cboFormatString.Items.Remove(format);
                cboFormatString.Items.Insert(1, format);
                cboFormatString.SelectedIndex = 1;
            }
            else
            {
                cboFormatString.Items.Insert(1, cboFormatString.Text);

                if(cboFormatString.Items.Count > 10)
                {
                    cboFormatString.Items.RemoveAt(10);
                }
            }

            StringCollection coll = new StringCollection();

            foreach (object item in cboFormatString.Items)
            {
                coll.Add((string) item);
            }

            TrackTitleEditorSettings.Default.FormatString = coll;
        }

        private void btnClearTitle_Click(object sender, EventArgs e)
        {
            IList<TrackTitle> tracks = _trackList.Objects;

            foreach (TrackTitle trackTitle in tracks)
            {
                trackTitle.Title = string.Empty;
                trackTitle.Tracknumber = string.Empty;
            }

            objectListView.Objects = tracks;
        }

        private void btnUpdate_Click(object sender, EventArgs e)
        {
            _tracks.Clear();

            _tracks.AddRange(_trackList.Objects);
        }

        private List<string> GetMissingTitles(DocumentLineCollection documentLines, IList<TrackTitle> tracks)
        {
            List<string> missing = new List<string>();
            
            int index = tracks.Count;

            for (int i = index; i < documentLines.Count; i++)
            {
                missing.Add(documentLines[i].Text);
            }

            return missing;
        }

        #endregion

        #region Toolbar Events.

        private void tsbNew_Click(object sender, EventArgs e)
        {
            New();
        }

        private void tsbOpen_Click(object sender, EventArgs e)
        {
            Open();
        }

        private void tsbSave_Click(object sender, EventArgs e)
        {
            Save();
        }

        private void tsbSaveAs_Click(object sender, EventArgs e)
        {
            SaveAs();
        }

        private void tsbPrintPreview_Click(object sender, EventArgs e)
        {
            PrintPreview();
        }

        private void tsbPrint_Click(object sender, EventArgs e)
        {
            Print();
        }

        private void tsbUndo_Click(object sender, EventArgs e)
        {
            Undo();
        }

        private void tsbRedo_Click(object sender, EventArgs e)
        {
            Redo();
        }

        private void tsbCut_Click(object sender, EventArgs e)
        {
            Cut();
        }

        private void tsbCopy_Click(object sender, EventArgs e)
        {
            Copy();
        }

        private void tsbPaste_Click(object sender, EventArgs e)
        {
            Paste();
        }

        private void tsbFind_Click(object sender, EventArgs e)
        {
            ShowFindAndReplace();
        }

        private void tsbGoto_Click(object sender, EventArgs e)
        {
            ShowGoTo();
        }

        private void tbsIncreaseIndent_Click(object sender, EventArgs e)
        {
            IncreaseIndent();
        }

        private void tsbDecreaseIndent_Click(object sender, EventArgs e)
        {
            DecreaseIndent();
        }

        private void tsbMoveUp_Click(object sender, EventArgs e)
        {
            MoveFileUp();
        }

        private void tsbMoveDown_Click(object sender, EventArgs e)
        {
            MoveFileDown();
        }

        private void tsbRunMacro_Click(object sender, EventArgs e)
        {
            RunMacro();
        }

        private void tsbRecordMacro_Click(object sender, EventArgs e)
        {
            RecordMacro();
        }

        private void tsbPauseMacro_Click(object sender, EventArgs e)
        {
            PauseMacro();
        }

        private void tsbCancelMacro_Click(object sender, EventArgs e)
        {
            CancelMacro();
        }

        #endregion

        #region Menu Events.

        private void mnuNew_Click(object sender, EventArgs e)
        {
            New();
        }

        private void mnuOpen_Click(object sender, EventArgs e)
        {
            Open();
        }

        private void mnuSave_Click(object sender, EventArgs e)
        {
            Save();
        }

        private void mnuSaveAs_Click(object sender, EventArgs e)
        {
            SaveAs();
        }

        private void mnuPrintPreview_Click(object sender, EventArgs e)
        {
            PrintPreview();
        }

        private void mnuPrint_Click(object sender, EventArgs e)
        {
            Print();
        }

        private void mnuPageSetup_Click(object sender, EventArgs e)
        {
            PageSetup();
        }

        private void mnuPrintNow_Click(object sender, EventArgs e)
        {
            PrintNow();
        }

        private void mnuClose_Click(object sender, EventArgs e)
        {
            btnCancel.PerformClick();
        }

        private void mnuUndo_Click(object sender, EventArgs e)
        {
            Undo();
        }

        private void mnuRedo_Click(object sender, EventArgs e)
        {
            Redo();
        }

        private void mnuCut_Click(object sender, EventArgs e)
        {
            Cut();
        }

        private void mnuCopy_Click(object sender, EventArgs e)
        {
            Copy();
        }

        private void mnuPaste_Click(object sender, EventArgs e)
        {
            Paste();
        }

        private void mnuCutAppend_Click(object sender, EventArgs e)
        {
            CutAndAppend();
        }

        private void mnuCopyAppend_Click(object sender, EventArgs e)
        {
            CopyAndAppend();
        }

        private void mnuClearClipboard_Click(object sender, EventArgs e)
        {
            ClearClipboard();
        }

        private void mnuDelete_Click(object sender, EventArgs e)
        {
            Delete();
        }

        private void mnuSelectAll_Click(object sender, EventArgs e)
        {
            SelectAll();
        }

        private void mnuSelectLine_Click(object sender, EventArgs e)
        {
            SelectLine();
        }

        private void mnuSelectWord_Click(object sender, EventArgs e)
        {
            SelectWord();
        }

        private void mnuSelectNone_Click(object sender, EventArgs e)
        {
            SelectNone();
        }

        private void mnuFindAndReplace_Click(object sender, EventArgs e)
        {
            ShowFindAndReplace();
        }

        private void mnuGoto_Click(object sender, EventArgs e)
        {
            ShowGoTo();
        }

        private void mnuMakeUppercase_Click(object sender, EventArgs e)
        {
            MakeUppercase();
        }

        private void mnuMakeLowercase_Click(object sender, EventArgs e)
        {
            MakeLowercase();
        }

        private void mnuCapitalize_Click(object sender, EventArgs e)
        {
            Capitalize();
        }

        private void mnuInvertCase_Click(object sender, EventArgs e)
        {
            InvertCasing();
        }

        private void mnuIncreaseLineIndent_Click(object sender, EventArgs e)
        {
            IncreaseIndent();
        }

        private void mnuDecreaseLineIndent_Click(object sender, EventArgs e)
        {
            DecreaseIndent();
        }

        private void mnuConvertTabsToSpaces_Click(object sender, EventArgs e)
        {
            ConvertTabsToSpaces();
        }

        private void mnuConvertSpacesToTabs_Click(object sender, EventArgs e)
        {
            ConvertSpacesToTabs();
        }

        private void mnuTabifySelectedLines_Click(object sender, EventArgs e)
        {
            TabifySelection();
        }

        private void mnuUntabifySelectedLines_Click(object sender, EventArgs e)
        {
            UntabifySelection();
        }

        private void mnuTrimTrailingWhitepace_Click(object sender, EventArgs e)
        {
            TrimTrailingSpace();
        }

        private void mnuTrimLeadingWhitespace_Click(object sender, EventArgs e)
        {
            TrimLeadingSpace();
        }

        private void mnuTrimLeadingAndTrailingSpace_Click(object sender, EventArgs e)
        {
            TrimLeadingAndTrailingSpace();
        }

        private void mnuDeleteHorizontalWhitespace_Click(object sender, EventArgs e)
        {
            DeleteHorizontalWhiteSpace();
        }

        private void mnuDeleteLine_Click(object sender, EventArgs e)
        {
            DeleteLine();
        }

        private void mnuDuplicateLine_Click(object sender, EventArgs e)
        {
            DuplicateLine();
        }

        private void mnuDeleteBlankLines_Click(object sender, EventArgs e)
        {
            DeleteBlankLines();
        }

        private void mnuTransposeLine_Click(object sender, EventArgs e)
        {
            TransposeLines();
        }

        private void mnuTransposeWord_Click(object sender, EventArgs e)
        {
            TransposeWords();
        }

        private void mnuTransposeCharacters_Click(object sender, EventArgs e)
        {
            TransposeCharacters();
        }

        private void mnuShowWhiteSpaceAndTab_Click(object sender, EventArgs e)
        {
            syntaxEditor.WhitespaceSpacesVisible = syntaxEditor.WhitespaceTabsVisible = !syntaxEditor.WhitespaceSpacesVisible;
            OnSettingsChanged();
        }

        private void mnuShowEndOfLine_Click(object sender, EventArgs e)
        {
            syntaxEditor.WhitespaceLineEndsVisible = !syntaxEditor.WhitespaceLineEndsVisible;
            OnSettingsChanged();
        }

        private void mnuMarkLineModifications_Click(object sender, EventArgs e)
        {
            syntaxEditor.Document.LineModificationMarkingEnabled = !syntaxEditor.Document.LineModificationMarkingEnabled;
            OnSettingsChanged();
        }

        private void mnuHighlightCurrentLine_Click(object sender, EventArgs e)
        {
            syntaxEditor.CurrentLineHighlightingVisible = !syntaxEditor.CurrentLineHighlightingVisible;
            OnSettingsChanged();
        }

        private void mnuShowColumn80Guide_Click(object sender, EventArgs e)
        {
            syntaxEditor.ColumnGuides.Clear();
            if (!mnuShowColumn80Guide.Checked)
            {
                syntaxEditor.ColumnGuides.Add(new ColumnGuide(ColumnGuideValueType.Column, 80, SystemColors.ControlDark));
            }

            OnSettingsChanged();

            syntaxEditor.Invalidate();
        }

        private void mnuRunMacro_Click(object sender, EventArgs e)
        {
            RunMacro();
        }

        private void mnuStartRecording_Click(object sender, EventArgs e)
        {
            RecordMacro();
        }

        private void mnuPauseRecording_Click(object sender, EventArgs e)
        {
            PauseMacro();
        }

        private void mnuCancelRecording_Click(object sender, EventArgs e)
        {
            CancelMacro();
        }

        #endregion

        #region Common Toolbar And Menu Methods.

        private void New()
        {
            syntaxEditor.Document.Text = "";

            _currentFilePath = "New Track List";

            Text = string.Format("Track Title Editor [{0}]", _currentFilePath);

            RefreshUndoRedoStatus(false, false);

            SetSaveStatus(true);

            SetDocumentSaveStatus(true);

            syntaxEditor.Enabled = true;

            syntaxEditor.Document.Modified = true;
        }

        private void Open()
        {
            openFileDialog.Title = "Open Text File";
            openFileDialog.Filter = "Text Files(*.txt)|*.txt";
            openFileDialog.FilterIndex = 1;
            openFileDialog.InitialDirectory = _currentDirectoryPath;

            DialogResult dlgResult = openFileDialog.ShowDialog(this);

            if (dlgResult == DialogResult.OK)
            {
                Open(openFileDialog.FileName);
            }
        }

        private void Open(string path)
        {
            try
            {
                syntaxEditor.Document.LoadFile(path, Encoding.UTF8);

                _currentFilePath = path;

                Text = string.Format("Track Title Editor [{0}]", path);

                RefreshUndoRedoStatus(false, false);

                SetSaveStatus(false);

                SetDocumentSaveStatus(false);

                syntaxEditor.Enabled = true;

                MruMenu.AddFile(path);
            }
            catch (Exception)
            {
                const string message = "The selected text file could not be opened for edit!";

                MessageBox.Show(this, message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void Save()
        {
            if( _currentFilePath == "New Track List")
            {
                SaveAs();
            }
            else
            {
                try
                {
                    syntaxEditor.Document.SaveFile(_currentFilePath, Encoding.UTF8, LineTerminator.CarriageReturnNewline);
                    SetSaveStatus(false);
                    SetDocumentSaveStatus(false);
                    syntaxEditor.Document.Modified = false;
                }
                catch (Exception ex)
                {
                    string message = string.Format("There was a problem saving changes to the text file [{0}]\n\n{1}", syntaxEditor.Document.Filename, ex.Message);

                    MessageBox.Show(this, message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void SaveAs()
        {
            saveFileDialog.Title = @"Save Text File As";
            saveFileDialog.Filter = "Text Files(*.txt)|*.txt";
            saveFileDialog.FilterIndex = 1;
            saveFileDialog.InitialDirectory = _currentDirectoryPath;

            DialogResult dlgResult = saveFileDialog.ShowDialog(this);

            if(dlgResult == DialogResult.OK)
            {
                try
                {
                    syntaxEditor.Document.SaveFile(saveFileDialog.FileName, Encoding.UTF8, LineTerminator.CarriageReturnNewline);
                    _currentFilePath = saveFileDialog.FileName;
                    Text = string.Format("Track Title Editor [{0}]", saveFileDialog.FileName);
                    RefreshUndoRedoStatus(false, false);
                    SetSaveStatus(false);
                    SetDocumentSaveStatus(false);
                    syntaxEditor.Document.Modified = false;

                    if(MruMenu.FindFilenameNumber(saveFileDialog.FileName) == -1)
                    {
                        MruMenu.AddFile(saveFileDialog.FileName);   
                    }
                }
                catch (Exception ex)
                {
                    string message = string.Format("There was a problem saving changes to the Text-file [{0}]\n\n{1}", syntaxEditor.Document.Filename, ex.Message);

                    MessageBox.Show(this, message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void Print()
        {
            if (!syntaxEditor.Document.HasContent)
            {
                return;
            }

            string docName = GetPrintingDocumentName(syntaxEditor.Document.Filename);

            syntaxEditor.PrintSettings.PrintDocument.DocumentName = docName;

            printDialog.Document = syntaxEditor.PrintSettings.PrintDocument;

            printDialog.AllowSelection = true;

            printDialog.AllowSomePages = true;

            DialogResult print = printDialog.ShowDialog(this);

            if (print == DialogResult.OK)
            {
                string date = DateTime.Now.ToShortDateString();
                string time = DateTime.Now.ToShortTimeString();
                string title = string.Format("{0} {1} {2}", syntaxEditor.Document.Filename, date, time);

                syntaxEditor.PrintSettings.DocumentTitle = Functions.ShortenName(title, PrintDocumentMaxLengthName);
                syntaxEditor.PrintSettings.PrintDocument.PrinterSettings = printDialog.PrinterSettings;
                syntaxEditor.PrintSettings.PrintDocument.Print();
            }
        }

        private void PrintPreview()
        {
            if (syntaxEditor == null)
            {
                return;
            }

            if (!syntaxEditor.Document.HasContent)
            {
                return;
            }

            string docName = GetPrintingDocumentName(syntaxEditor.Document.Filename);

            var s = new Size(1200, 900);

            printPreviewDialog.Size = s;
            printPreviewDialog.StartPosition = FormStartPosition.CenterScreen;
            printPreviewDialog.PrintPreviewControl.Zoom = 1.0;
            printPreviewDialog.Text = String.Format("Preview {0}", docName);

            string date = DateTime.Now.ToShortDateString();
            string time = DateTime.Now.ToShortTimeString();
            string title = string.Format("{0} {1} {2}", syntaxEditor.Document.Filename, date, time);

            syntaxEditor.PrintSettings.DocumentTitle = Functions.ShortenName(title, PrintDocumentMaxLengthName);

            printPreviewDialog.Document = syntaxEditor.PrintSettings.PrintDocument;
            printPreviewDialog.Document.DocumentName = docName;
            printPreviewDialog.ShowDialog(this);
        }

        private void PageSetup()
        {
            syntaxEditor.ShowPageSetupForm(this);
        }

        private void PrintNow()
        {
            if (!syntaxEditor.Document.HasContent)
            {
                return;
            }

            string docName = GetPrintingDocumentName(syntaxEditor.Document.Filename);
            string date = DateTime.Now.ToShortDateString();
            string time = DateTime.Now.ToShortTimeString();
            string title = string.Format("{0} {1} {2}", syntaxEditor.Document.Filename, date, time);

            syntaxEditor.PrintSettings.PrintDocument.DocumentName = docName;
            syntaxEditor.PrintSettings.DocumentTitle = Functions.ShortenName(title, PrintDocumentMaxLengthName);
            syntaxEditor.Print(false);
        }

        private void Undo()
        {
            syntaxEditor.Document.UndoRedo.Undo();
        }

        private void Redo()
        {
            syntaxEditor.Document.UndoRedo.Redo();
        }

        private void Cut()
        {
            if (!syntaxEditor.Document.HasContent)
                return;

            syntaxEditor.SelectedView.CutToClipboard();
            HasClipboardText();
        }

        private void Copy()
        {
            if (!syntaxEditor.Document.HasContent)
                return;

            syntaxEditor.SelectedView.CopyToClipboard();
            HasClipboardText();
        }

        private void Paste()
        {
            if (syntaxEditor.Enabled)
            {
                syntaxEditor.SelectedView.PasteFromClipboard();
            }
        }

        private void CutAndAppend()
        {
            syntaxEditor.SelectedView.CutAndAppendToClipboard();
        }

        private void CopyAndAppend()
        {
            syntaxEditor.SelectedView.CopyAndAppendToClipboard();
        }

        private void ClearClipboard()
        {
            if (Clipboard.ContainsText(TextDataFormat.UnicodeText) || Clipboard.ContainsText(TextDataFormat.Text))
            {
                Clipboard.Clear();
                HasClipboardText();
            }
        }

        private void Delete()
        {
            syntaxEditor.SelectedView.Delete();
        }

        private void SelectAll()
        {
            syntaxEditor.SelectedView.Selection.SelectAll();
        }

        private void SelectLine()
        {
            syntaxEditor.SelectedView.Selection.MoveToLineStart();
            syntaxEditor.SelectedView.Selection.SelectToLineEnd();
        }

        private void SelectWord()
        {
            syntaxEditor.SelectedView.Selection.SelectWord();
        }

        private void SelectNone()
        {
            int offset = syntaxEditor.SelectedView.Selection.FirstOffset;
            syntaxEditor.SelectedView.Selection.SelectRange(offset, 0);
        }

        private void ShowFindAndReplace()
        {
            if (_findReplaceForm == null)
            {
                _findReplaceForm = new FormFindReplace(syntaxEditor, _findReplaceOptions);
            }

            _findReplaceForm.Owner = this;

            if (_findReplaceForm.Visible)
                _findReplaceForm.Activate();
            else
                _findReplaceForm.Show();
        }

        private void ShowGoTo()
        {
            if (syntaxEditor.Document.HasContent)
            {
                FormGotoLine frm = new FormGotoLine(syntaxEditor);

                frm.ShowDialog(this);
            }
        }

        private void MakeUppercase()
        {
            syntaxEditor.SelectedView.ChangeCharacterCasing(CharacterCasing.Upper);
        }

        private void MakeLowercase()
        {
            syntaxEditor.SelectedView.ChangeCharacterCasing(CharacterCasing.Lower);
        }

        private void Capitalize()
        {
            syntaxEditor.SelectedView.ChangeCharacterCasing(CharacterCasing.Lower);
            syntaxEditor.SelectedView.ChangeCharacterCasing(CharacterCasing.Normal);
        }

        private void InvertCasing()
        {
            syntaxEditor.SelectedView.SelectedText = Functions.InvertCasing(syntaxEditor.SelectedView.SelectedText);
        }

        private void TrimTrailingSpace()
        {
            DocumentPosition position = syntaxEditor.Caret.DocumentPosition;

            DocumentLineCollection lines = syntaxEditor.Document.Lines;

            for (int i = 0; i < lines.Count; i++)
            {
                lines[i].Text = lines[i].Text.TrimEnd();
            }

            syntaxEditor.Caret.Offset = syntaxEditor.Document.PositionToOffset(position);
        }

        private void TrimLeadingSpace()
        {
            DocumentPosition position = syntaxEditor.Caret.DocumentPosition;

            DocumentLineCollection lines = syntaxEditor.Document.Lines;

            for (int i = 0; i < lines.Count; i++)
            {
                lines[i].Text = lines[i].Text.TrimStart();
            }

            syntaxEditor.Caret.Offset = syntaxEditor.Document.PositionToOffset(position);
        }

        private void TrimLeadingAndTrailingSpace()
        {
            DocumentPosition position = syntaxEditor.Caret.DocumentPosition;

            DocumentLineCollection lines = syntaxEditor.Document.Lines;

            for (int i = 0; i < lines.Count; i++)
            {
                lines[i].Text = lines[i].Text.TrimStart();
                lines[i].Text = lines[i].Text.TrimEnd();
            }

            syntaxEditor.Caret.Offset = syntaxEditor.Document.PositionToOffset(position);
        }

        private void IncreaseIndent()
        {
            syntaxEditor.SelectedView.Indent();
        }

        private void DecreaseIndent()
        {
            syntaxEditor.SelectedView.Outdent();
        }

        private void ConvertTabsToSpaces()
        {
            syntaxEditor.SelectedView.ConvertTabsToSpaces();
        }

        private void ConvertSpacesToTabs()
        {
            syntaxEditor.SelectedView.ConvertSpacesToTabs();
        }

        private void TabifySelection()
        {
            syntaxEditor.SelectedView.TabifySelectedLines();
        }

        private void UntabifySelection()
        {
            syntaxEditor.SelectedView.UntabifySelectedLines();
        }

        private void DeleteHorizontalWhiteSpace()
        {
            syntaxEditor.SelectedView.DeleteHorizontalWhitespace();
        }

        private void DeleteLine()
        {
            syntaxEditor.SelectedView.DeleteLine();
        }

        private void DeleteBlankLines()
        {
            syntaxEditor.SelectedView.DeleteBlankLines();
        }

        private void DuplicateLine()
        {
            syntaxEditor.SelectedView.DuplicateLine();
        }

        private void TransposeCharacters()
        {
            syntaxEditor.SelectedView.TransposeCharacters();
        }

        private void TransposeWords()
        {
            syntaxEditor.SelectedView.TransposeWords();
        }

        private void TransposeLines()
        {
            syntaxEditor.SelectedView.TransposeLines();
        }

        private void RunMacro()
        {
            syntaxEditor.SelectedView.RaiseEditCommand(new RunMacroCommand());
        }

        private void RecordMacro()
        {
            syntaxEditor.SelectedView.RaiseEditCommand(new ToggleMacroRecordingCommand());
        }

        private void PauseMacro()
        {
            syntaxEditor.SelectedView.RaiseEditCommand(new PauseResumeMacroRecordingCommand());
        }

        private void CancelMacro()
        {
            syntaxEditor.SelectedView.RaiseEditCommand(new CancelMacroRecordingCommand());
        }

        private void syntaxEditor_MacroRecordingStateChanged(object sender, EventArgs e)
        {
            switch (syntaxEditor.MacroRecording.State)
            {
                case MacroRecordingState.Recording:
                    tsbRunMacro.Enabled = false;
                    tsbRecordMacro.ImageIndex = 1;  // Stop button
                    mnuStartRecording.Image = imlMenu.Images[1];
                    tsbRecordMacro.ToolTipText = @"Stop Recording";
                    tsbPauseMacro.Enabled = true;
                    tsbPauseMacro.Checked = false;
                    tsbPauseMacro.ToolTipText = @"Pause Recording";
                    tsbCancelMacro.Enabled = true;
                    break;
                case MacroRecordingState.Paused:
                    tsbPauseMacro.Checked = true;
                    tsbPauseMacro.ToolTipText = @"Resume Recording";
                    break;
                default:
                    tsbRunMacro.Enabled = (syntaxEditor.MacroRecording.LastMacroCommand != null);
                    tsbRecordMacro.ImageIndex = 0;  // Record button
                    mnuStartRecording.Image = imlMenu.Images[0];
                    tsbRecordMacro.ToolTipText = @"Record Macro";
                    tsbPauseMacro.Enabled = false;
                    tsbPauseMacro.Checked = false;
                    tsbPauseMacro.ToolTipText = @"Pause Recording";
                    tsbCancelMacro.Enabled = false;
                    break;
            }

            mnuRunMacro.Enabled = tsbRunMacro.Enabled;
            mnuStartRecording.Text = tsbRecordMacro.ToolTipText;
            mnuPauseRecording.Enabled = tsbPauseMacro.Enabled;
            mnuPauseRecording.Text = tsbPauseMacro.ToolTipText;
            mnuCancelRecording.Enabled = tsbCancelMacro.Enabled;
        }

        #endregion

        #region Event Implementation.

        private void UndoRedoStateChanged(object sender, UndoRedoStateChangedEventArgs e)
        {
            SetUndoRedoStatus(e.Document.UndoRedo.CanUndo, e.Document.UndoRedo.CanRedo);
        }

        #endregion

        #region Syntax Editor Events.

        private void syntaxEditor_DocumentTextChanged(object sender, DocumentModificationEventArgs e)
        {
            slbTotalLines.Text = string.Format("Total Lines: {0:# ##0}", syntaxEditor.Document.Lines.Count);

            SetDocumentSaveStatus(syntaxEditor.Document.Modified);

            SetSaveStatus(syntaxEditor.Document.Modified);
        }

        private void syntaxEditor_OverwriteModeChanged(object sender, EventArgs e)
        {
            SetWriteType();
        }

        private void syntaxEditor_DocumentModifiedChanged(object sender, EventArgs e)
        {
            SetDocumentSaveStatus(syntaxEditor.Document.Modified);
        }

        #endregion

        #region ObjectListView Events.

        private void objectListView_AfterSorting(object sender, AfterSortingEventArgs e)
        {
            _isSorted = true;
        }

        private void objectListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            if (_trackList.SelectedObjects.Count > 0)
            {
                tsbMoveDown.Enabled = true;
                tsbMoveUp.Enabled = true;
            }
            else
            {
                tsbMoveDown.Enabled = false;
                tsbMoveUp.Enabled = false;
            }
        }

        #endregion

        #region Helper Methods.

        private void RepaintObjectListView()
        {
            foreach (OLVListItem item in objectListView.Items)
            {
                if (item.Index % 2 != 0)
                {
                    item.BackColor = Color.FromArgb(192, 255, 192);
                }
                else
                {
                    item.BackColor = Color.FromArgb(255, 255, 255);
                }
            }
        }

        private static string GetPrintingDocumentName(string viewName)
        {
            string docName;

            if (string.IsNullOrEmpty(viewName))
            {
                docName = "Track Title List - No Name";
            }
            else
            {
                docName = string.Format("Track Title List - {0}", viewName);
            }

            return docName;
        }

        private void SetWriteType()
        {
            if (syntaxEditor.OverwriteMode)
            {
                slbWriteMode.Text = @"OVR";
            }
            else
            {
                slbWriteMode.Text = @"INS";
            }
        }

        private void SetSaveStatus(bool canSave)
        {
            tsbSave.Enabled = canSave;
            mnuSave.Enabled = canSave;
        }

        private void SetDocumentSaveStatus(bool isModified)
        {
            if (!syntaxEditor.Document.HasContent)
                return;

            if (Disposing)
                return;

            if (isModified)
            {
                if (!Text.EndsWith("*"))
                {
                    Text += @" *";
                }
            }
            else
            {
                if (Text.EndsWith("*"))
                {
                    Text = Text.Substring(0, Text.Length - 2);
                }
            }
        }

        private void SetUndoRedoStatus(bool undo, bool redo)
        {
            mnuUndo.Enabled = undo;
            mnuRedo.Enabled = redo;

            tsbUndo.Enabled = undo;
            tsbRedo.Enabled = redo;

            if (!undo)
            {
                SetSaveStatus(false);
                SetDocumentSaveStatus(false);
                syntaxEditor.Document.Modified = false;
            }
            else
            {
                SetSaveStatus(true);
                SetDocumentSaveStatus(true);
                syntaxEditor.Document.Modified = true;
            }
        }

        private void RefreshUndoRedoStatus(bool undo, bool redo)
        {
            mnuUndo.Enabled = undo;
            mnuRedo.Enabled = redo;

            tsbUndo.Enabled = undo;
            tsbRedo.Enabled = redo;
        }

        private void HasClipboardText()
        {
            if (Clipboard.ContainsText(TextDataFormat.UnicodeText) || Clipboard.ContainsText(TextDataFormat.Text))
            {
                tsbPaste.Enabled = true;
                mnuPaste.Enabled = true;
                mnuCopyAppend.Enabled = true;
                mnuCutAppend.Enabled = true;
                mnuClearClipboard.Enabled = true;
            }
            else
            {
                tsbPaste.Enabled = false;
                mnuPaste.Enabled = false;
                mnuCopyAppend.Enabled = false;
                mnuCutAppend.Enabled = false;
                mnuClearClipboard.Enabled = false;
            }
        }

        private void OnSettingsChanged()
        {
            mnuShowWhiteSpaceAndTab.Checked = syntaxEditor.WhitespaceSpacesVisible;
            mnuShowEndOfLine.Checked = syntaxEditor.WhitespaceLineEndsVisible;
            mnuMarkLineModifications.Checked = syntaxEditor.Document.LineModificationMarkingEnabled;
            mnuHighlightCurrentLine.Checked = syntaxEditor.CurrentLineHighlightingVisible;
            mnuShowColumn80Guide.Checked = !mnuShowColumn80Guide.Checked;
            //menuBracketMatchingStyle.Checked = _editorSettings.BracketMatchingStyle == BracketMatchingStyle.After;
            //menuEnableVirtualSpace.Checked = _editorSettings.AllowCaretBeyondEOL;
            //menuShowLineNumbers.Checked = _editorSettings.ShowLineNumbers;
        }

        private void MoveFileUp()
        {
            if (_trackList.SelectedObjects.Count > 0)
            {
                if (_trackList.ListView.SelectedItems[0].Index == 0)
                {
                    return;
                }

                _trackList.ListView.BeginUpdate();

                if (_isSorted)
                {
                    _trackList.ListView.Unsort();
                    _isSorted = false;
                }

                foreach (ListViewItem listViewItem in _trackList.ListView.SelectedItems)
                {
                    int tmp = listViewItem.Index;

                    _trackList.ListView.Items.Remove(listViewItem);

                    _trackList.ListView.Items.Insert(tmp - 1, listViewItem);
                }
                
                _trackList.ListView.RefreshObjects((IList)_trackList.Objects);

                RepaintObjectListView();
                
                _trackList.ListView.EndUpdate();
            }
        }

        private void MoveFileDown()
        {
            if (_trackList.SelectedObjects.Count > 0)
            {
                if (_trackList.ListView.SelectedItems[_trackList.SelectedObjects.Count - 1].Index == _trackList.Objects.Count - 1)
                {
                    return;
                }

                _trackList.ListView.BeginUpdate();

                if (_isSorted)
                {
                    _trackList.ListView.Unsort();
                    _isSorted = false;
                }

                foreach (ListViewItem listViewItem in _trackList.ListView.SelectedItems)
                {
                    int tmp = listViewItem.Index;
                    int selected = _trackList.SelectedObjects.Count;

                    _trackList.ListView.Items.Remove(listViewItem);

                    _trackList.ListView.Items.Insert(tmp + selected, listViewItem);
                }
                
                _trackList.ListView.RefreshObject((IList)_trackList.Objects);

                RepaintObjectListView();

                _trackList.ListView.EndUpdate();
            }
        }

        #endregion        

        #region Format String.

        private void btnFormat_Click(object sender, EventArgs e)
        {
            cxmButton.Show(btnFormat, new Point(btnFormat.ClientRectangle.Right, btnFormat.ClientRectangle.Top));
        }

        private void cmuTitle_Click(object sender, EventArgs e)
        {
            if (!cboFormatString.Text.Contains(cmuTitle.Tag.ToString()))
                cboFormatString.Text = BuildFormatString(_selectedFormatIndex, cboFormatString.Text, cmuTitle.Tag.ToString());
        }

        private void cmuTrack_Click(object sender, EventArgs e)
        {
            if(!cboFormatString.Text.Contains(cmuTrack.Tag.ToString()))
                cboFormatString.Text = BuildFormatString(_selectedFormatIndex, cboFormatString.Text, cmuTrack.Tag.ToString());
        }

        private void cmuClear_Click(object sender, EventArgs e)
        {
            cboFormatString.Text = string.Empty;
        }

        private string BuildFormatString(int index, string currentFormat, string addedFormat)
        {
            string retvalue = currentFormat;

            retvalue = retvalue.Insert(index, addedFormat);

            return retvalue;
        }

        private void cboFormatString_Click(object sender, EventArgs e)
        {
            _selectedFormatIndex = cboFormatString.SelectionStart;
        }

        private void cboFormatString_TextChanged(object sender, EventArgs e)
        {
            _selectedFormatIndex = cboFormatString.SelectionStart;

            if(string.IsNullOrEmpty(cboFormatString.Text))
            {
                btnPreview.Enabled = false;
                btnUpdate.Enabled = false;
            }
            else
            {
                btnPreview.Enabled = true;
                btnUpdate.Enabled = true;
            }
        }

        private void cboFormatString_KeyUp(object sender, KeyEventArgs e)
        {
            _selectedFormatIndex = cboFormatString.SelectionStart;
        }

        private string TrimStartEnd(string text)
        {
            string result = text;

            result = result.TrimStart();
            result = result.TrimEnd();

            return result;
        }

        private void CreateTagsFromFormatString(string formatString, string textLine, TrackTitle track)
        {
            List<string> tagList = new List<string>();
            List<string> splitterList = new List<string>();

            string format = TrimStartEnd(formatString);
            string line = TrimStartEnd(textLine);

            string[] splitter = new[] {"%"};

            string[] formatArr = format.Split(splitter, StringSplitOptions.RemoveEmptyEntries);

            foreach (string s in formatArr)
            {
                switch (s)
                {
                    case "Track":
                    case "Title":
                        tagList.Add(s);
                        break;
                    default:
                        splitterList.Add(s);
                        break;
                }
            }

            string[] result = line.Split(splitterList.ToArray(), splitterList.Count + 1, StringSplitOptions.RemoveEmptyEntries);

            int index = 0;

            foreach (string tag in tagList)
            {
                bool removeTrack = !tagList.Contains("Track");
                bool removeTitle = !tagList.Contains("Title");

                switch (tag)
                {
                    case "Track":
                        track.Tracknumber = result[index];
                        break;
                    case "Title":
                        track.Title = result[index];
                        break;
                    default:
                        break;
                }

                if (removeTrack)
                    track.Tracknumber = string.Empty;
                if (removeTitle)
                    track.Title = string.Empty;

                index++;

                if(index >= result.Length)
                    break;
            }
        }

        #endregion

        private void mnuLookUpAbbrivations_Click(object sender, EventArgs e)
        {
            LookUpAbbrivations();
        }

        private void tsbAbbrivations_Click(object sender, EventArgs e)
        {
            LookUpAbbrivations();
        }

        private void LookUpAbbrivations()
        {
            var frm = new FormAbbreviations();

            frm.ShowDialog(this);
        }

        private void FormTitleEditor_Resize(object sender, EventArgs e)
        {
            splitContainer.SplitterDistance = Width / 2;
        }
    }
}
